package cn.itcast.demo;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.io.IOException;
@SuppressWarnings("all")
public class LuceneIndexQueryIndex {
    @Test
    public void testQueryIndex() throws IOException, ParseException {

//        查询转换的工具，使用这个工具可以转换出对象
        //创建查询解析器，两个参数：默认要查询的字段的名称，分词器
        QueryParser queryParser = new QueryParser("title",new IKAnalyzer());
        //创建查询对象
        Query query = queryParser.parse("谷歌");
        search(query);
    }
//  多字段查询功能
    @Test
    public void testMuitlQueryIndex() throws IOException, ParseException {

        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(new String[]{"id","title"},new IKAnalyzer());
//        查询转换的工具，使用这个工具可以转换出对象
//        QueryParser queryParser = new QueryParser("title",new IKAnalyzer());
        //创建查询对象
        Query query = queryParser.parse("3");
        search(query);
    }
//  词条查询没有分词器,词条查询不能分词，写什么就会把什么当成词条词库中有才能查到
    @Test
    public void testTermQuery() throws IOException {
        Query query = new TermQuery(new Term("title","谷歌"));
        search(query);
    }
//  通配符查询 通配符有?(只能是一个)和*(0个或多个)
    @Test
    public void testWildcardQuery() throws IOException {
        Query query = new WildcardQuery(new Term("title","谷歌?"));
        search(query);
    }

//  模糊查询 移动火柴棍，最大编辑距离为2，默认为2，取值为0-2
    @Test
    public void testFuzzyQuery() throws IOException {
        Query query = new FuzzyQuery(new Term("title","facebooc"),1);
        search(query);
    }
    //数值范围查询,如果类型为String之类的字符串的时候可以直接查询，因为类型对应
    //如果字段类型为数值类型，就不能直接查
    @Test
    public void testNumericRangeQuery() throws IOException {
        Query query = NumericRangeQuery.newLongRange("id",3L,3L,true,true);
        search(query);
    }
    //MUST VS MUST 相当于&&， SHOULE VS SHOULD 相当于 ||，MUST_NOT相当于!
    @Test
    public void testBooleanQuery() throws IOException {
        Query query1 = NumericRangeQuery.newLongRange("id",2L,4L,true,true);
        Query query2 = NumericRangeQuery.newLongRange("id",3L,5L,true,true);
        BooleanQuery query = new BooleanQuery();
//        query.add(query1,BooleanClause.Occur.MUST);
//        query.add(query2,BooleanClause.Occur.MUST);
//        query.add(query1,BooleanClause.Occur.SHOULD);
//        query.add(query2,BooleanClause.Occur.SHOULD);
        query.add(query1,BooleanClause.Occur.MUST_NOT);
        query.add(query2,BooleanClause.Occur.MUST);

        search(query);
    }
    public void search(Query query) throws IOException {
        //目录
        Directory directory = FSDirectory.open(new File("indexDir"));

        //把目录中的数据或内容全部读取出来
        IndexReader indexReader = DirectoryReader.open(directory);

        //索引的查询对象，或者叫索引的检索对象
        IndexSearcher searcher = new IndexSearcher(indexReader);

        //搜索条件，执行搜索，需要传入搜索条件，以及要搜索的数量,返回符合条件的前N个文档
        TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
        //表示实际命中的个数
        int totalHits = topDocs.totalHits;
        System.out.println("命中了 = " + totalHits);

        //得分文档数组
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        int length = scoreDocs.length;

        System.out.println("真正的查到的数量="+length);

        for (ScoreDoc scoreDoc : scoreDocs) {
            //当前文档的得分
            float score = scoreDoc.score;
            //当前文档的编号
            int docId = scoreDoc.doc;

            Document document = searcher.doc(docId);

            String id = document.get("id");
            String title = document.get("title");
            System.out.println("得分:"+score+"id:"+id+"title:"+title);
        }
    }
}
